#include "SpriteD3D10.h"


Sprite::SpriteD3D10::SpriteD3D10():m_ISwapChain(NULL)
{
	SpriteD3D::SpriteD3D();
	m_d3dDriverType = D3D10_DRIVER_TYPE_HARDWARE;
	m_DepthStencilBuffer = NULL;
	m_RenderTargetView = NULL;
	m_DepthStencilView = NULL;
}

Sprite::SpriteD3D10::~SpriteD3D10( void )
{

	ReleaseCOM(m_ISwapChain);
	ReleaseCOM( m_DepthStencilBuffer);
	ReleaseCOM(m_RenderTargetView);
	ReleaseCOM(m_DepthStencilView);
}

HRESULT Sprite::SpriteD3D10::initD3D( HWND HMainWnd,int nWidth,int nHeight )
{
	HR(SpriteD3D::initD3D(HMainWnd,nWidth,nHeight));
	// Fill out a DXGI_SWAP_CHAIN_DESC to describe our swap chain.


	m_descSwapChain.BufferDesc.Width  = m_nWidth;
	m_descSwapChain.BufferDesc.Height = m_nHeight;
	m_descSwapChain.BufferDesc.RefreshRate.Numerator = 60;
	m_descSwapChain.BufferDesc.RefreshRate.Denominator = 1;
	m_descSwapChain.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	m_descSwapChain.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
	m_descSwapChain.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;

	// No multisampling.
	m_descSwapChain.SampleDesc.Count   = 1;
	m_descSwapChain.SampleDesc.Quality = 0;

	m_descSwapChain.BufferUsage  = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	m_descSwapChain.BufferCount  = 1;
	m_descSwapChain.OutputWindow = m_HMainWnd;
	m_descSwapChain.Windowed     = true;
	m_descSwapChain.SwapEffect   = DXGI_SWAP_EFFECT_DISCARD;
	m_descSwapChain.Flags        = 0;


	// Create the device.

	UINT createDeviceFlags = 0;
#if defined(DEBUG) || defined(_DEBUG)  
	createDeviceFlags |= D3D10_CREATE_DEVICE_DEBUG;
#endif

	HR( D3D10CreateDeviceAndSwapChain(
		0,                 //default adapter
		m_d3dDriverType,
		0,                 // no software device
		createDeviceFlags, 
		D3D10_SDK_VERSION,
		&m_descSwapChain,
		&	m_ISwapChain,
		&m_IDevice10) );


	// The remaining steps that need to be carried out for d3d creation
	// also need to be executed every time the window is resized.  So
	// just call the onResize method here to avoid code duplication.

	//	onResize();
	return S_OK;
}

void Sprite::SpriteD3D10::resetOMTargetsAndViewport()
{
	m_IDevice10->OMSetRenderTargets(1, &m_RenderTargetView, m_DepthStencilView);

	D3D10_VIEWPORT vp;
	vp.TopLeftX = 0;
	vp.TopLeftY = 0;
	vp.Width    = m_nWidth;
	vp.Height   = m_nHeight;
	vp.MinDepth = 0.0f;
	vp.MaxDepth = 1.0f;

	m_IDevice10->RSSetViewports(1, &vp);
}

void Sprite::SpriteD3D10::onResize()
{
	// Release the old views, as they hold references to the buffers we
	// will be destroying.  Also release the old depth/stencil buffer.

	ReleaseCOM(m_RenderTargetView);
	ReleaseCOM(m_DepthStencilView);
	ReleaseCOM(m_DepthStencilBuffer);


	// Resize the swap chain and recreate the render target view.

	HR(m_ISwapChain->ResizeBuffers(1, m_nWidth, m_nHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
	ID3D10Texture2D* backBuffer;
	HR(m_ISwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), reinterpret_cast<void**>(&backBuffer)));
	HR(m_IDevice10->CreateRenderTargetView(backBuffer, 0, &m_RenderTargetView));
	ReleaseCOM(backBuffer);


	// Create the depth/stencil buffer and view.

	D3D10_TEXTURE2D_DESC depthStencilDesc;

	depthStencilDesc.Width     = m_nWidth;
	depthStencilDesc.Height    = m_nHeight;
	depthStencilDesc.MipLevels = 1;
	depthStencilDesc.ArraySize = 1;
	depthStencilDesc.Format    = DXGI_FORMAT_D24_UNORM_S8_UINT;
	depthStencilDesc.SampleDesc.Count   = 1; // multisampling must match
	depthStencilDesc.SampleDesc.Quality = 0; // swap chain values.
	depthStencilDesc.Usage          = D3D10_USAGE_DEFAULT;
	depthStencilDesc.BindFlags      = D3D10_BIND_DEPTH_STENCIL;
	depthStencilDesc.CPUAccessFlags = 0; 
	depthStencilDesc.MiscFlags      = 0;

	HR(m_IDevice10->CreateTexture2D(&depthStencilDesc, 0, &m_DepthStencilBuffer));
	HR(m_IDevice10->CreateDepthStencilView(m_DepthStencilBuffer, 0, &m_DepthStencilView));


	// Bind the render target view and depth/stencil view to the pipeline.

	m_IDevice10->OMSetRenderTargets(1, &m_RenderTargetView, m_DepthStencilView);


	// Set the viewport transform.

	D3D10_VIEWPORT vp;
	vp.TopLeftX = 0;
	vp.TopLeftY = 0;
	vp.Width    = m_nWidth;
	vp.Height   = m_nHeight;
	vp.MinDepth = 0.0f;
	vp.MaxDepth = 1.0f;

	m_IDevice10->RSSetViewports(1, &vp);

	float aspect = (float)m_nWidth/m_nHeight;
	
		
	D3DXMatrixPerspectiveFovLH(&m_pProjMat,0.25f*PI,aspect,1.0f,1000.0f);
}

void Sprite::SpriteD3D10::onResize( int nWidth,int nHeight )
{
	SpriteD3D::onResize(nWidth,nHeight);
}
void Sprite::SpriteD3D10::clear()
{
	m_IDevice10->ClearRenderTargetView(m_RenderTargetView,SpriteColor(1,1,1,1));
	m_IDevice10->ClearDepthStencilView(m_DepthStencilView, D3D10_CLEAR_DEPTH|D3D10_CLEAR_STENCIL, 1.0f, 0);
}

void Sprite::SpriteD3D10::begin()
{
	this->clear();
}

void Sprite::SpriteD3D10::end()
{
	m_ISwapChain->Present(0,0);
}
